//Version 1.0 Release
//Version 1.1 Fixed bugs, added deathwalk, and spiffied antiBan.
//Version 1.2 Better chopping, same method but used camera angles.
//Version 1.3 Fixed the banking problem
//Version 1.4 Okay made the chopping a lot better.
//Version 1.5 A lot better banking.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.Map;

import javax.imageio.ImageIO;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.script.Calculations;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;
import com.speljohan.rsbot.script.wrappers.RSTilePath;

public class DraynorWillowCut extends Script implements ServerMessageListener,
		PaintListener {
	public static double getOVersion() {
		try {
			final URL url = new URL(
					"http://megaalgosscripts.110mb.com/RimmingtonYewCut.txt");
			final BufferedReader br = new BufferedReader(new InputStreamReader(
					new BufferedInputStream(url.openConnection()
							.getInputStream())));
			final double ver = Double.parseDouble(br.readLine().trim());
			br.close();
			return ver;
		} catch (final IOException e) {
			throw new RuntimeException(e);
		}
	}

	// Varibles
	int counter = 1;

	int capital;

	long startTime = 0;

	public int logs = 0;

	RSNPC ent;
	int[] Axes = { 1351, 1349, 1353, 1355, 1361, 1357, 1359, 6739 };
	int ENT = 0;
	int level;
	int[] trees = { 5553, 5551, 5552 };
	public int[] numberhr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
	int bankBooth = 2213;
	int startwclvl = skills.getCurrentSkillLevel(8);
	boolean camera = true;
	RSTile[] bankWalk1 = new RSTile[] { new RSTile(3087, 3233),
			new RSTile(3086, 3241), new RSTile(3093, 3242) };
	RSTilePath bankWalk = new RSTilePath(bankWalk1, this);
	RSTile[] deathWalk = new RSTile[] { new RSTile(3233, 3222),
			new RSTile(3228, 3234), new RSTile(3219, 3246),
			new RSTile(3203, 3246), new RSTile(3187, 3245),
			new RSTile(3173, 3240), new RSTile(3158, 3234),
			new RSTile(3143, 3229), new RSTile(3126, 3225),
			new RSTile(3112, 3222), new RSTile(3099, 3227),
			new RSTile(3089, 3230) };
	RSTilePath DEATHWALK = new RSTilePath(deathWalk, this);

	public int antiBan() {
		Point mouse;
		final int x = random(0, 750);
		final int y = random(0, 500);
		final int xx = random(710, 554);
		final int yy = random(444, 230);
		final int screenx = random(1, 510);
		final int screeny = random(1, 450);

		final int gamble = random(0, 22);
		switch (gamble) {
		case 1:
			wait(random(1000, 2500));
			return random(500, 750);
		case 2:
			moveMouse(x, y);
			wait(random(1000, 2500));
			return random(500, 750);
		case 3:
			openTab(Constants.TAB_INVENTORY);
			wait(random(1000, 2500));
			return random(200, 400);
		case 4:
			if (getMyPlayer().isMoving()) {
				wait(random(1000, 2500));
				return random(750, 1000);
			}
		case 5:
			moveMouse(x, y);
			int checkTime = 0;
			long lastCheck = 0;
			wait(random(1000, 2500));
			if (System.currentTimeMillis() - lastCheck >= checkTime) {
				lastCheck = System.currentTimeMillis();
				checkTime = random(60000, 180000);
				return random(500, 800);
			}
		case 6:
			if (getCurrentTab() != Constants.TAB_STATS) {
				openTab(Constants.TAB_STATS);
				moveMouse(xx, yy);
				wait(random(2000, 3500));
				return random(1000, 3000);
			}
		case 7:
			turnCamera();
			wait(random(2000, 3000));
			return random(500, 750);
		case 8:
			moveMouse(screenx, screeny);
			wait(random(2000, 3000));
			return random(100, 320);
		case 9:
			moveMouse(screenx, screeny);
			wait(random(2000, 3000));
			return random(100, 320);
		case 10:
			randomTab();
			wait(random(2000, 3000));
			return random(120, 250);

		case 11:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);
		case 13:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);
		case 12:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);
		case 14:
			mouse = getMouseLocation();
			wait(random(300, 500));
			moveMouse(mouse, 20, 20);
			wait(random(100, 200));
			return random(100, 320);
		case 15:
			mouse = getMouseLocation();
			wait(random(300, 500));
			moveMouse(mouse, 20, 20);
			wait(random(100, 200));
			return random(100, 320);
		case 16:
			mouse = getMouseLocation();
			wait(random(300, 500));
			moveMouse(mouse, 20, 20);
			wait(random(100, 200));
			return random(100, 320);
		case 17:
			mouse = getMouseLocation();
			wait(random(300, 500));
			moveMouse(mouse, 20, 20);
			wait(random(100, 200));
			return random(100, 320);
		case 19:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);
		case 20:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);
		case 21:
			moveMouse(x, y);
			wait(random(2000, 3000));
			return random(100, 320);

		}
		return random(100, 250);
	}

	public boolean atLumby() {
		if (rectangle(3217, 3225, 3213, 3224)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean attackedByEnt() {
		ent = null;
		ent = getNearestNPCByName("Willow");
		if (ent == null || getMyPlayer().getInteracting() == null) {
			return false;
		}
		return getMyPlayer().getInteracting().equals(ent);
	}

	public void checkEnt() {
		ent = null;
		ent = getNearestNPCByName("Willow");
		if (getMyPlayer().getInteracting().equals(ent)) {
			atTile(getMyPlayer().getLocation(), "walk here");
		}
	}

	// End

	public int chopTree(final RSObject tree) {
		int X, Y;
		X = (int) Calculations.tileToScreen(tree.getLocation()).getX();
		Y = (int) Calculations.tileToScreen(tree.getLocation()).getY();

		if (getCameraAngle() > 0 && getCameraAngle() < 45) {
			X += random(39, 57);
			Y -= random(33, 39);
		}

		if (getCameraAngle() > 45 && getCameraAngle() < 90) {
			X += random(22, 29);
			Y -= random(13, 19);
		}

		if (getCameraAngle() > 90 && getCameraAngle() < 135) {
			X += random(0, 4);
			Y += random(12, 18);
		}

		if (getCameraAngle() > 135 && getCameraAngle() < 180) {
			X += random(2, 4);
			Y += random(10, 14);
		}

		if (getCameraAngle() > 180 && getCameraAngle() < 225) {
			X -= random(35, 45);
			Y += random(-3, 3);
		}

		if (getCameraAngle() > 225 && getCameraAngle() < 270) {
			X -= random(3, 10);
			Y -= random(15, 25);
		}

		if (getCameraAngle() > 270 && getCameraAngle() < 315) {
			X += random(-5, 5);
			Y -= random(40, 60);
		}

		if (getCameraAngle() > 315 && getCameraAngle() < 360) {
			X += 0;
			Y -= random(30, 40);
		}
		final Point newtree = new Point(X, Y);
		moveMouse(newtree);
		clickMouse(true);
		return random(200, 500);
	}

	public boolean clickObject(final RSObject c, final String action) {
		try {
			Point screenLoc = null;
			int X = (int) Calculations.tileToScreen(c.getLocation()).getX();
			int Y = (int) Calculations.tileToScreen(c.getLocation()).getY();
			for (int i = 0; i < 12; i++) {
				screenLoc = new Point(X, Y);
				if (c == null || !pointOnScreen(screenLoc)) {
					log.info("Not on screen " + action);
					return false;
				}
				if (getMouseLocation().equals(screenLoc)) {
					break;
				}
				moveMouse(screenLoc);
			}
			X = (int) Calculations.tileToScreen(c.getLocation()).getX();
			Y = (int) Calculations.tileToScreen(c.getLocation()).getY();
			screenLoc = new Point(X, Y);
			if (!getMouseLocation().equals(screenLoc)) {
				return false;
			}

			clickMouse(screenLoc, false);
			return atMenu(action);

		} catch (final NullPointerException e) {
		}
		return true;
	}

	public int deposit() {
		try {
			final RSObject bankbooth = findObject(bankBooth);
			if (bankbooth != null) {
				clickObject(bankbooth, "use-quickly");
			}
			if (bank.getInterface().isValid()) {
				bank.depositAllExcept(Axes);
				wait(random(1500, 2100));
				atInterface(Constants.INTERFACE_BANK,
						Constants.INTERFACE_BANK_BUTTON_CLOSE);
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
		return random(100, 300);
	}

	@Override
	public String getAuthor() {
		return "Megaalgos";
	}

	@Override
	public String getName() {
		return "DraynorWillowCut";
	}

	@Override
	public String getScriptCategory() {
		return "Woodcutting";
	}

	@Override
	public String getScriptDescription() {
		String html = "";

		html += "<html>\n";
		html += "<head></head>";
		html += "<body>\n";
		html += "<h2>" + getName() + " v" + getVersion() + "</h2><br>\n";
		html += "Author: " + getAuthor() + "<br><br>\n";
		html += "Just start by the willows with an axe.";
		html += "Any questions add my msn- megaalgos@hotmail.com";
		html += "</center>\n";
		html += "</body>\n";
		html += "</html\n";
		return html;
	}

	@Override
	public double getVersion() {
		return 1.5;
	}

	public boolean goingDraynor() {

		for (final RSTile element : deathWalk) {
			if (distanceTo(element) < 17) {
				return true;
			}

		}
		return false;
	}

	public boolean inBank() {
		if (rectangle(3087, 3098, 3240, 3246)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean inDraynor() {

		for (final RSTile element : bankWalk1) {
			if (distanceTo(element) < 15) {
				return true;
			}

		}
		return false;
	}

	public boolean inLumbyToDraynor() {
		if (rectangle(3102, 3242, 3199, 3267)) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int loop() {
		final RSObject tree = findObject(trees);
		try {
			switch (capital) {
			case 0:
				if (getEnergy() > random(50, 99) && !isRunning()) {
					setRun(true);
				}
				if (isLoggedIn() && camera == true) {
					setCameraAltitude(true);
					startwclvl = skills.getCurrentSkillLevel(8);
					camera = false;
				}
				if (goingDraynor() && !inDraynor()) {
					log("Going to draynor...");
					DEATHWALK.walkToEnd();
					return random(100, 200);
				}
				if (onPath(bankWalk1) || onPath(deathWalk)) {
				} else {
					openTab(Constants.TAB_MAGIC);
					castSpell(1);
					wait(random(30000, 50000));
					return random(100, 300);
				}

				if (atLumby()) {
					log("Going to draynor...");
					DEATHWALK.walkToEnd();
					return random(100, 200);
				}
				if (attackedByEnt()) {
					ENT++;
					log("Ent found!!!");
					checkEnt();
					return random(100, 200);
				}
				if (getMyPlayer().isInCombat()) {
					log("In combat!!");
					return capital = 2;
				}
				if (getMyPlayer().getAnimation() != -1) {
					return antiBan();
				}
				if (isInventoryFull()) {
					log("Inventory full going to bank...");
					return capital++;
				}
				if (inBank()) {
					log("In bank going to trees...");
					bankWalk.walkToStart();
				}
				if (getMyPlayer().isMoving()) {
					wait(random(100, 1000));
					return antiBan();
				}
				final RSTile TreeT = tree.getLocation();
				if (tree == null) {
					walkTileMM(TreeT);
					turnCamera();
				}
				if (tree != null) {
					if (distanceTo(TreeT) >= 5) {
						walkTileMM(TreeT);
						return antiBan();
					}
					chopTree(tree);
					wait(random(2000, 3000));

					if (random(1, 5) == 3) {
						turnCamera();
					}
				}

				if (getMyPlayer().getAnimation() != -1) {
					return antiBan();
				}

				break;
			case 1:
				if (isInventoryFull()) {
					if (getEnergy() <= random(1, 30)) {
						setRun(false);
					}
					walkToBank();
					wait(random(3000, 4000));
				}
				if (isInventoryFull()) {
					deposit();
					wait(random(1000, 2000));
					if (getEnergy() > random(50, 99)) {
						setRun(true);
					}
					capital = 0;
					return random(100, 250);
				}
				break;
			case 2:
				if (getMyPlayer().isInCombat()) {
					walkToBank();
					wait(random(3000, 5000));
					antiBan();
					return capital = 0;
				}
				break;
			}
		} catch (final Exception e) {
			log("Somethings wrong......");
			e.printStackTrace();
		}
		return random(500, 1000);
	}

	@Override
	public void onFinish() {
		final long runTime = System.currentTimeMillis() - startTime;
		final long TotalSecs = runTime / 1000;
		final long TotalMins = TotalSecs / 60;
		final long TotalHours = TotalMins / 60;
		final int seconds = (int) TotalSecs % 60;
		final int minutes = (int) TotalMins % 60;
		final int hours = (int) TotalHours % 60;

		final StringBuilder b = new StringBuilder();

		if (hours < 10) {
			b.append('0');
		}
		b.append(hours);
		b.append(':');
		if (minutes < 10) {
			b.append('0');
		}
		b.append(minutes);
		b.append(':');
		if (seconds < 10) {
			b.append('0');
		}
		b.append(seconds);
		log("Cut: " + logs + " logs");
		log("Ran for: " + b.toString());
		Bot.getEventManager().removeListener(ServerMessageListener.class, this);
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public boolean onPath(final RSTile[] t) {
		for (final RSTile element : t) {
			if (distanceTo(element) < 15) {
				return true;
			}
		}
		return false;
	}

	public void onRepaint(Graphics g) {
		final long runTime = System.currentTimeMillis() - startTime;
		final long TotalSecs = runTime / 1000;
		final long TotalMins = TotalSecs / 60;
		final long TotalHours = TotalMins / 60;
		final int seconds = (int) TotalSecs % 60;
		final int minutes = (int) TotalMins % 60;
		final int hours = (int) TotalHours % 60;
		final int currentwclvl = skills.getCurrentSkillLevel(8);

		final StringBuilder b = new StringBuilder();
		final double workmin = logs / (minutes + hours * 60 + seconds / 60f);
		final double work = logs / (minutes + hours * 60 + seconds / 60f) * 60f;

		if (hours < 10) {
			b.append('0');
		}
		b.append(hours);
		b.append(':');
		if (minutes < 10) {
			b.append('0');
		}
		b.append(minutes);
		b.append(':');
		if (seconds < 10) {
			b.append('0');
		}
		b.append(seconds);

		if (minutes == 30 && seconds == 1 || minutes == 0 && seconds == 30
				&& isLoggedIn()) {
			try {
				final BufferedImage img = new BufferedImage(185, 155,
						BufferedImage.TYPE_INT_RGB);
				final File file = new File("DraynorWillowCut" + counter
						+ ".gif");
				g = img.getGraphics();
				g.setColor(new Color(76, 67, 69));
				g.fill3DRect(0, 0, 185, 155, true);

				final int w = 0;
				int z = 0;
				g.setColor(new Color(80, 207, 58));
				g.drawString("Ran for: " + b.toString(), w, z += 25);
				g.drawString("Cut: " + logs + " logs", w, z += 20);
				g.drawString("Gained: " + level + " levels.", w, z += 20);
				g.drawString("Cutting: " + roundToTenth(workmin) + " per min.",
						w, z += 20);
				g.drawString("Cutting: " + roundToTenth(work) + " per hour.",
						w, z += 20);
				g.drawString("Starting woocutting lvl: " + startwclvl, w,
						z += 20);
				g.drawString("Current woodcutting lvl:" + currentwclvl, w,
						z += 20);
				ImageIO.write(img, "gif", file);
				log("Sent a proggy to folder...");
				counter++;
				wait(random(1000, 2500));
			} catch (final IOException e) {
				e.printStackTrace();
				log("Wrong");
			}
		}

		try {
			if (isLoggedIn()) {
				g.setColor(new Color(76, 67, 69, 185));
				g.fill3DRect(11, 225, 185, 155, true);
				final int x = 10;
				int y = 225;
				g.setColor(new Color(80, 207, 58));
				g.drawString("Ran for: " + b.toString(), x, y += 25);
				g.drawString("Cut: " + logs + " logs", x, y += 20);
				g.drawString("Gained: " + level + " levels.", x, y += 20);
				g.drawString("Cutting: " + roundToTenth(workmin) + " per min.",
						x, y += 20);
				g.drawString("Cutting: " + roundToTenth(work) + " per hour.",
						x, y += 20);
				g.drawString("Starting woocutting lvl: " + startwclvl, x,
						y += 20);
				g.drawString("Current woodcutting lvl:" + currentwclvl, x,
						y += 20);
			}
		} catch (final NumberFormatException e) {
		}

	}

	// End
	@Override
	public boolean onStart(final Map<String, String> args) {
		startTime = System.currentTimeMillis();
		startTime = System.currentTimeMillis();
		if (DraynorWillowCut.getOVersion() == getVersion()) {
			log("You are up to date.");
		} else {
			log("You need to get the updated version here: http://www.rsbot.org/vb/showthread.php?t=13265 ");
		}
		return true;
	}

	public int randomTab() {
		final int random1 = random(1, 23);
		switch (random1) {
		case 1:
			openTab(Constants.TAB_STATS);
			return random(100, 500);
		case 2:
			openTab(Constants.TAB_ATTACK);
			return random(100, 500);

		case 3:
			openTab(Constants.TAB_QUESTS);
			return random(100, 500);

		case 4:
			openTab(Constants.TAB_EQUIPMENT);
			return random(100, 500);

		case 5:
			openTab(Constants.TAB_INVENTORY);
			return random(100, 500);
		case 6:
			openTab(Constants.TAB_PRAYER);
			return random(100, 500);
		case 7:
			openTab(Constants.TAB_MAGIC);
			return random(100, 500);

		case 8:
			openTab(Constants.TAB_SUMMONING);
			return random(100, 500);

		case 9:
			openTab(Constants.TAB_FRIENDS);
			return random(100, 500);
		case 10:
			openTab(Constants.TAB_IGNORE);
			return random(100, 500);

		case 11:
			openTab(Constants.TAB_CLAN);
			return random(100, 500);

		case 12:
			openTab(Constants.TAB_CONTROLS);
			return random(100, 500);
		case 13:
			openTab(Constants.TAB_MUSIC);
			return random(100, 500);
		case 14:
			openTab(Constants.TAB_OPTIONS);
			return random(100, 500);
		}
		return random(100, 300);
	}

	// From last man3
	public boolean rectangle(final int x1, final int x2, final int y1,
			final int y2) {
		final int posX = getMyPlayer().getLocation().getX();
		final int posY = getMyPlayer().getLocation().getY();
		if (posX >= x1 && posX <= x2 && posY >= y1 && posY <= y2) {
			return true;
		} else {
			return false;
		}
	}

	public double roundToTenth(final double d) {
		DecimalFormat twoDForm = new DecimalFormat("#.#");
		try {
			twoDForm = new DecimalFormat("#.#");
		} catch (final NumberFormatException e) {
		}
		return Double.valueOf(twoDForm.format(d));
	}

	public void serverMessageRecieved(final ServerMessageEvent arg0) {
		final String serverString = arg0.getMessage();
		if (serverString.equals("You get some willow logs.")) {
			logs++;
		}
		if (serverString.contains("You've just advanced a Woodcutting level!")) {
			level++;
		}
	}

	// Methods
	public void turnCamera() {
		final char[] LR = new char[] { KeyEvent.VK_LEFT, KeyEvent.VK_UP };
		final char[] UD = new char[] { KeyEvent.VK_UP, KeyEvent.VK_LEFT };
		final char[] LRUD = new char[] { KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
				KeyEvent.VK_UP, KeyEvent.VK_LEFT };
		final int random2 = random(0, 2);
		final int random1 = random(0, 2);
		final int random4 = random(0, 4);

		if (random(0, 3) == 0) {
			Bot.getInputManager().pressKey(LR[random1]);
			try {
				Thread.sleep(random(100, 400));
			} catch (final Exception e) {
			}
			Bot.getInputManager().pressKey(UD[random2]);
			try {
				Thread.sleep(random(300, 600));
			} catch (final Exception e) {
			}
			Bot.getInputManager().releaseKey(UD[random2]);
			try {
				Thread.sleep(random(100, 400));
			} catch (final Exception e) {
			}
			Bot.getInputManager().releaseKey(LR[random1]);
		} else {
			Bot.getInputManager().pressKey(LRUD[random4]);
			if (random4 > 1) {
				try {
					Thread.sleep(random(300, 600));
				} catch (final Exception e) {
				}
			} else {
				try {
					Thread.sleep(random(500, 900));
				} catch (final Exception e) {
				}
			}
			Bot.getInputManager().releaseKey(LRUD[random4]);
		}
	}

	public boolean walkToBank() {
		try {
			bankWalk.walkToEnd();
		} catch (final Exception e) {
			e.printStackTrace();
		}
		return false;
	}
}